home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 4.iso / src / demos / GL / curve / draw.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-08-02  |  16.1 KB  |  813 lines

  1. /*
  2.  * Copyright 1991, 1992, 1993, 1994, Silicon Graphics, Inc.
  3.  * All Rights Reserved.
  4.  *
  5.  * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
  6.  * the contents of this file may not be disclosed to third parties, copied or
  7.  * duplicated in any form, in whole or in part, without the prior written
  8.  * permission of Silicon Graphics, Inc.
  9.  *
  10.  * RESTRICTED RIGHTS LEGEND:
  11.  * Use, duplication or disclosure by the Government is subject to restrictions
  12.  * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
  13.  * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
  14.  * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
  15.  * rights reserved under the Copyright Laws of the United States.
  16.  */
  17. /*
  18.  *
  19.  * draw.c
  20.  *
  21.  * Part of the "Curve Demo"
  22.  * by Howard Look for Silicon Graphics
  23.  *
  24.  * June, 1989
  25.  *
  26.  * This file contains the routines used for drawing on the screen,
  27.  * including drawing the curve, the control points, and the view
  28.  * volume. This file also contains routines for maintaining the position 
  29.  * and motion of the control points.
  30.  *
  31.  */
  32.  
  33.  
  34. #include <stdio.h>
  35. #include <gl.h>
  36. #include <device.h>
  37. #include <math.h>
  38. #include "curve.h"
  39. #include "event.h"
  40. #include "spaced.h"
  41.  
  42.  
  43. /* Prototypes */
  44. void init_basis(void);
  45. void init_linestyles(void);
  46. void clear_window(void);
  47. void draw_display(void);
  48. void draw_markers(void);
  49. void draw_hulls(void);
  50. void draw_drop_lines(Coord c[3]);
  51. void update_positions(void);
  52. void add_control_point(void);
  53. void delete_control_point(void);
  54. void move_control_point(int);
  55. void track_motion();
  56. int get_close_marker(float, float);
  57. float generate_random_float(float);
  58. void draw_cube(void);
  59. void draw_volume(void);
  60. Boolean hit_control_point(int *);
  61. void fake_view_volume(void);
  62. void fake_control_volume(void);
  63.  
  64. extern void help(int);
  65. extern Boolean helping(void);
  66.  
  67. extern Boolean within_cube(void);
  68.  
  69. /* basis matrix for Bezier splines */
  70. Matrix bezier_matrix =
  71.     {    {-1.0,  3.0, -3.0, 1.0}, 
  72.         { 3.0, -6.0,  3.0, 0.0},
  73.         {-3.0,  3.0,  0.0, 0.0},
  74.         { 1.0,  0.0,  0.0, 0.0}
  75.     };
  76.  
  77.  
  78. /* basis matrix for cardinal splines */
  79. Matrix cardinal_matrix =
  80.     {    {-0.5,  1.5, -1.5,  0.5}, 
  81.         { 1.0, -2.5,  2.0, -0.5}, 
  82.         {-0.5,  0.0,  0.5,  0.0}, 
  83.         { 0.0,  1.0,  0.0,  0.0}
  84.     };
  85.  
  86.  
  87. /* basis matrix for B-splines */
  88. Matrix bspline_matrix =
  89.     {    {-1.0/6.0,  3.0/6.0, -3.0/6.0, 1.0/6.0}, 
  90.         { 3.0/6.0, -6.0/6.0,  3.0/6.0,     0.0}, 
  91.         {-3.0/6.0,      0.0,  3.0/6.0,     0.0}, 
  92.         { 1.0/6.0,  4.0/6.0,  1.0/6.0,     0.0} 
  93.     };
  94.  
  95.  
  96. /* Array of control points that define the geometry of the curve */
  97. Coord geometry[MAX_MARKERS][3];
  98.  
  99.  
  100. /* Array of dx,dy,dz for each control point, used to create motion */
  101. float offset[MAX_MARKERS][3];
  102.  
  103.  
  104. /* Number of control point markers currently being used */
  105. int current_markers = 0;
  106.  
  107.  
  108. /* 
  109.  * if motion is on while trying to move a point, nail that point to
  110.  * the cursor.
  111.  */
  112. Boolean moving = FALSE;
  113. int nailed_marker;
  114.  
  115. Matrix everything_matrix;
  116.  
  117. /* Environment variables */
  118. extern 
  119. int        curve_basis, 
  120.         display_mode, 
  121.         curve_precision,
  122.         speed, 
  123.         line_style, 
  124.         whizbang;
  125. extern
  126. Boolean    markers,
  127.         hulls,
  128.         motion, 
  129.         smear;
  130.  
  131. extern
  132. int hardware;
  133.  
  134.         
  135. /* About the window... */ 
  136. extern int origin_x, origin_y, size_x, size_y;
  137.  
  138.  
  139. /* Rotation matrix for the view volume */
  140. extern Matrix rotate_matrix;
  141.  
  142.  
  143. /* 
  144.  * Defines the basis matrices so we can use them later.
  145.  */
  146. void init_basis(void)
  147. {
  148.     defbasis(BEZIER, bezier_matrix);
  149.     defbasis(CARDINAL, cardinal_matrix);
  150.     defbasis(BSPLINE, bspline_matrix);
  151. }
  152.  
  153.  
  154. /*
  155.  * Initializes the linestyles so we can use them.
  156.  */
  157. void init_linestyles(void)
  158. {
  159.     /* Solid pattern is pre-defined */
  160.     deflinestyle(DOTTED, DOTTED_PATTERN);
  161.     deflinestyle(DASHED, DASHED_PATTERN);
  162. }
  163.  
  164. /* 
  165.  * Completely draws the display.  Called by the event manager whenever
  166.  * there is no event queue activity.
  167.  */
  168. void draw_display(void)
  169. {
  170.     if (!current_markers)
  171.     {
  172.         help(TRUE);
  173.         return;
  174.     }
  175.     if (helping())
  176.     {
  177.         draw_instructions(FALSE);
  178.         return;
  179.     }
  180.     
  181.     if (! smear)
  182.         czclear(0,getgdesc(GD_ZMAX));
  183.  
  184.     if (display_mode == THREE_D)
  185.     {
  186.         set_three_d_view();
  187.         /* apply the view volume's rotation matrix */
  188.         multmatrix(rotate_matrix);
  189.  
  190.         if (hardware != ECLIPSE8)
  191.             /* depth cue markers and curve in white */
  192.             lRGBrange(50, 50, 50, 255, 255, 255,
  193.                   getgdesc(GD_ZMIN), getgdesc(GD_ZMAX));
  194.     }
  195.     else
  196.     {
  197.         if (hardware != ECLIPSE8)
  198.             cpack(0xffffff);
  199.             
  200.         set_two_d_view();
  201.     }
  202.  
  203.     if (hardware == ECLIPSE8)
  204.         color(WHITE);
  205.  
  206.     /* display the control point marker */
  207.     if (markers)
  208.         draw_markers();
  209.  
  210.     /* 3 control points doth not a curve make */
  211.     if (current_markers > 3)
  212.     {
  213.         setlinestyle(line_style);
  214.         
  215.         /* Draw the curve with multiple control points */
  216.         crvn(current_markers, geometry);
  217.  
  218.         if(motion)
  219.             update_positions();
  220.     }
  221.  
  222.     /* display the convex hulls */
  223.     if (hulls)
  224.     {
  225.         setlinestyle(SOLID);
  226.         
  227.         if (display_mode == THREE_D)
  228.         {
  229.             if(hardware != ECLIPSE8)
  230.                 lRGBrange(0, 50, 0, 0, 255, 0, 
  231.                       getgdesc(GD_ZMIN), getgdesc(GD_ZMAX));
  232.         }
  233.         else if (hardware != ECLIPSE8)
  234.             cpack(0xff00);
  235.  
  236.         if (hardware == ECLIPSE8) color(GREEN);
  237.         
  238.         draw_hulls();
  239.     }
  240.             
  241.  
  242.  
  243.     if (display_mode == THREE_D)
  244.     {    
  245.         /* depth cue the cube in red */
  246.         setlinestyle(SOLID);
  247.         
  248.         if (hardware != ECLIPSE8)
  249.             lRGBrange(100, 0, 0, 255, 0, 0,
  250.                   getgdesc(GD_ZMIN), getgdesc(GD_ZMAX));
  251.         else
  252.             color(RED);
  253.             
  254.         draw_cube();
  255.  
  256.         if (moving)
  257.         {
  258.             if (hardware != ECLIPSE8)
  259.                 lRGBrange(0,50,50,0,255,255,
  260.                       getgdesc(GD_ZMIN), getgdesc(GD_ZMAX));
  261.             else
  262.                 color(CYAN);
  263.  
  264.             draw_drop_lines(geometry[nailed_marker]);
  265.         }
  266.     }
  267.  
  268.     /* if smearing, we are already drawing in front buffer */
  269.     if (! smear)
  270.         swapbuffers();
  271. }
  272.  
  273.  
  274. /*
  275.  * Clears the window and reinitialized the control point markers to
  276.  * none.
  277.  */
  278. void clear_window(void)
  279. {
  280.     current_markers = 0;
  281.  
  282.     czclear(0,getgdesc(GD_ZMAX));
  283.     
  284.     draw_display();
  285. }
  286.  
  287.  
  288. /*
  289.  * Draws the digits representing the control point markers on the
  290.  * screen. The actual control point is the character's lower-left
  291.  * origin.
  292.  */
  293. void draw_markers(void)
  294. {
  295.     int i;
  296.     char marker_string[3];
  297.  
  298.     for (i=0; i<current_markers; i++)
  299.     {
  300.         sprintf(marker_string, "%d", i);
  301.         cmov(geometry[i][0], geometry[i][1], geometry[i][2]);
  302.         charstr(marker_string);
  303.     }
  304. }
  305.  
  306.  
  307.  
  308. void draw_drop_lines(Coord c[3])
  309. {
  310.     Coord a[3],b[3];
  311.  
  312.     a[0] = c[0];
  313.     a[1] = c[1];
  314.     a[2] = -1.0;
  315.     b[0] = c[0];
  316.     b[1] = c[1];
  317.     b[2] =  1.0;
  318.     bgnline();
  319.     v3f(a);
  320.     v3f(b);
  321.     endline();
  322.     
  323.     a[0] = c[0];
  324.     a[1] = -1.0;
  325.     a[2] = c[2];
  326.     b[0] = c[0];
  327.     b[1] = 1.0;
  328.     b[2] = c[2];
  329.     bgnline();
  330.     v3f(a);
  331.     v3f(b);
  332.     endline();
  333.     
  334.     a[0] = -1.0;
  335.     a[1] = c[1];
  336.     a[2] = c[2];
  337.     b[0] = 1.0;
  338.     b[1] = c[1];
  339.     b[2] = c[2];
  340.     bgnline();
  341.     v3f(a);
  342.     v3f(b);
  343.     endline(); 
  344. }
  345.  
  346.  
  347. /* Draw the convex hulls by connecting the series of control points
  348.  * with lines.
  349.  */
  350. void draw_hulls(void)
  351. {
  352.     int i;
  353.  
  354.     bgnline();
  355.     for (i=0; i<current_markers; i++)
  356.         v3f(geometry[i]);
  357.     endline();
  358. }
  359.  
  360.  
  361. /*
  362.  * Updates the positions of the control points by adding the offset
  363.  * for each dimension to the markers position. Checks for collisions
  364.  * with the walls of the view volume, which is defined between -1 and
  365.  * 1 along each axis. Note that even though the z component is ignored
  366.  * in 2D mode, it is updated anyway.
  367.  */
  368. void update_positions(void)
  369. {
  370.     int i, j;
  371.     float new_position, overshoot;
  372.  
  373.     /* for each control point marker */
  374.     for(i=0; i<current_markers; i++)
  375.     
  376.         if (!moving || (i != nailed_marker))
  377.         
  378.             /* for each dimension x,y,z */
  379.             for(j=0; j<3; j++)
  380.             {
  381.                 new_position = geometry[i][j] + (float)speed*offset[i][j];
  382.             
  383.                 if (new_position < -1.0)
  384.                 {
  385.                     offset[i][j] = -offset[i][j];
  386.                     overshoot = -1.0 - new_position;                    
  387.                     geometry[i][j] = -1.0 + overshoot;
  388.                 }
  389.                 else if (new_position > 1.0)
  390.                 {
  391.                     offset[i][j] = -offset[i][j];
  392.                     overshoot = new_position - 1.0;
  393.                     geometry[i][j] = 1.0 - overshoot;
  394.                 }
  395.                 else
  396.                     geometry[i][j] = new_position;
  397.             }
  398. }
  399.  
  400.  
  401.  
  402. static float last_x, last_y;
  403.  
  404.  
  405. /* 
  406.  * Called by the event manager whenever the left mouse button is pressed.
  407.  * Used to add a control point. In 2D mode, the control point is added
  408.  * at the exact location of the mouse click. In 3D mode, the point
  409.  * will be projected onto the z=0 plane, then is given a random z
  410.  * value. In both modes, points are given random offsets used to
  411.  * create motion. This offset is added to the control point's location
  412.  * whenever motion is active.
  413.  */
  414. void add_control_point(void)
  415. {
  416.     Coord x, y;
  417.     long mx, my;
  418.     
  419.     if (current_markers < MAX_MARKERS)
  420.     {
  421.         /* scale the offsets so they are not outrageous for the size
  422.            of the window (although the window may change) */
  423.         offset[current_markers][0] = (generate_random_float(2.0) -
  424.                     1.0)/(float)size_x;
  425.         offset[current_markers][1] = (generate_random_float(2.0) -
  426.                     1.0)/(float)size_y;
  427.         offset[current_markers][2] = (generate_random_float(2.0) -
  428.                     1.0)/(float)size_x;
  429.                         
  430.         if (display_mode == TWO_D)
  431.         {
  432.             /* Scale mouse values to square around -1.0 to 1.0  */
  433.             x = 2.0*((Coord)(getvaluator(MOUSEX) - origin_x)/size_x - 0.5);
  434.             y = 2.0*((Coord)(getvaluator(MOUSEY) - origin_y)/size_y    - 0.5);
  435.  
  436.             geometry[current_markers][0] = x;
  437.             geometry[current_markers][1] = y;
  438.             geometry[current_markers][2] = generate_random_float(2.0) - 1.0;
  439.  
  440.             /* scale the offsets so they are not outrageous for the size
  441.                of the window (although the window may change) */
  442.             offset[current_markers][0] = (generate_random_float(2.0) -
  443.                         1.0)/(float)size_x;
  444.             offset[current_markers][1] = (generate_random_float(2.0) -
  445.                         1.0)/(float)size_y;
  446.             offset[current_markers][2] = (generate_random_float(2.0) -
  447.                         1.0)/(float)size_x;
  448.  
  449.             nailed_marker = current_markers;
  450.             current_markers++;
  451.         
  452.             moving = TRUE;
  453.     
  454.             mx = getvaluator(MOUSEX);
  455.             my = getvaluator(MOUSEY);
  456.  
  457.             /* Scale mouse values to square around -1.0 to 1.0  */
  458.             last_x = 2.0*((Coord)(mx - origin_x)/size_x - 0.5);
  459.             last_y = 2.0*((Coord)(my - origin_y)/size_y - 0.5);
  460.  
  461.         }
  462.         else /* display_mode == THREE_D, use spaced */
  463.         {
  464.             if (within_cube)
  465.             {
  466.                 extern Coord box_limit[3][2];
  467.                 
  468.                 start_spaced();
  469.             
  470.                 geometry[current_markers][0] = 0.0;
  471.                 geometry[current_markers][1] = 0.0;
  472.                 geometry[current_markers][2] = 0.0;
  473.                 
  474.                 set_three_d_view();
  475.                 multmatrix(rotate_matrix);
  476.                 getmatrix(everything_matrix);
  477.             
  478.                 nailed_marker = current_markers;
  479.                 current_markers++;
  480.                 moving = TRUE;
  481.  
  482.                 spaced(everything_matrix, geometry[nailed_marker], box_limit);
  483.  
  484.                 /* next three lines compensate for a bug in spaced,
  485.                     they make the added point fall under the cursor */
  486.                 setvaluator(MOUSEX,getvaluator(MOUSEX)+1,0,XMAXSCREEN);
  487.                 setvaluator(MOUSEY,getvaluator(MOUSEY)+1,0,YMAXSCREEN);
  488.                 spaced(everything_matrix, geometry[nailed_marker], box_limit);
  489.             }
  490.         }
  491.         
  492.         qdevice(MOUSEX);
  493.         qdevice(MOUSEY);
  494.         draw_display();
  495.     }
  496. }
  497.  
  498.  
  499. /* 
  500.  * Called by the event manager whenever the backspace key is pressed.
  501.  * Deletes the control points closest to the cursor, renumbers the
  502.  * remaining control points, and redraws the curve.
  503.  */
  504. void delete_control_point(void)
  505. {
  506.     int i, j, close_marker;
  507.     float x, y; 
  508.  
  509.     if (current_markers)
  510.     {
  511.         /* Scale mouse values to square around -1.0 to 1.0  */
  512.         x = 2.0*((Coord)(getvaluator(MOUSEX) - origin_x)/size_x - 0.5);
  513.         y = 2.0*((Coord)(getvaluator(MOUSEY) - origin_y)/size_y    - 0.5);
  514.  
  515.         close_marker = get_close_marker(x, y);
  516.         
  517.         current_markers--;
  518.         for (i=close_marker; i<current_markers; i++)
  519.             for (j=0; j<3; j++)
  520.                 geometry[i][j] = geometry[i+1][j];
  521.  
  522.         draw_display();
  523.     }
  524. }
  525.  
  526.  
  527. /*
  528.  * Called by decode_middle_mouse whenever the middle mouse button is
  529.  * pressed and in 2D mode. Chooses the control point closest to the
  530.  * cursor and 'nails' the control point to the motion of the cursor.
  531.  * Tons of fun when motion is turned on.
  532.  */
  533. void move_control_point(int marker)
  534. {
  535.     Coord x, y;
  536.     long mx, my;
  537.     
  538.     if (display_mode == TWO_D)
  539.     {
  540.         nailed_marker = marker;
  541.         
  542.         moving = TRUE;
  543.     
  544.         mx = getvaluator(MOUSEX);
  545.         my = getvaluator(MOUSEY);
  546.  
  547.         /* Scale mouse values to square around -1.0 to 1.0  */
  548.         last_x = 2.0*((Coord)(mx - origin_x)/size_x - 0.5);
  549.         last_y = 2.0*((Coord)(my - origin_y)/size_y - 0.5);
  550.  
  551.     }
  552.     else /* display_mode == THREE_D, use spaced */
  553.     {
  554.         extern Coord box_limit[3][2];
  555.                 
  556.         start_spaced();
  557.             
  558.         set_three_d_view();
  559.         multmatrix(rotate_matrix);
  560.         getmatrix(everything_matrix);
  561.             
  562.         nailed_marker = marker;
  563.  
  564.         moving = TRUE;
  565.         spaced(everything_matrix, geometry[nailed_marker], box_limit);
  566.     }
  567.     qdevice(MOUSEX);
  568.     qdevice(MOUSEY);
  569.     draw_display();
  570. }
  571.  
  572.  
  573. void track_motion()
  574. {
  575.     long mx, my;
  576.     
  577.     /* Scaled mouse values */
  578.     float new_x, new_y, dx, dy;
  579.  
  580.     mx = getvaluator(MOUSEX);
  581.     my = getvaluator(MOUSEY);
  582.     
  583.     new_x = 2.0*((Coord)(mx - origin_x)/size_x - 0.5);
  584.     dx = new_x-last_x;
  585.     geometry[nailed_marker][0] += dx;
  586.             
  587.     /* stay bewteen the lines... */
  588.     if (geometry[nailed_marker][0] < -1.0)
  589.         geometry[nailed_marker][0] = -1.0;
  590.     else if (geometry[nailed_marker][0] > 1.0)
  591.         geometry[nailed_marker][0] = 1.0;
  592.             
  593.     last_x = new_x;
  594.         
  595.     new_y = 2.0*((Coord)(my - origin_y)/size_y - 0.5);
  596.     dy = new_y-last_y;
  597.     geometry[nailed_marker][1] += dy;
  598.             
  599.     if (geometry[nailed_marker][1] < -1.0)
  600.         geometry[nailed_marker][1] = -1.0;
  601.     else if (geometry[nailed_marker][1] > 1.0)
  602.         geometry[nailed_marker][1] = 1.0;
  603.                 
  604.     last_y = new_y;
  605. }
  606.  
  607.  
  608. /*
  609.  * Returns the index of the closest control point marker to x,y where
  610.  * x and y are in scaled screen coordinates between -1.0 and 1.0.
  611.  */
  612. int get_close_marker(float x, float y)
  613. {
  614.     float max_dist, current_dist, dx, dy;
  615.     int close_marker, i;
  616.     
  617.     /* furthest point can be in -1 to 1 square */
  618.     max_dist = 2.0*fsqrt(2.0);
  619.  
  620.     for(i=0; i<current_markers; i++)
  621.     {
  622.         dx = geometry[i][0] - x;
  623.         dy = geometry[i][1] - y;
  624.         current_dist = fsqrt(dx*dx + dy*dy);
  625.  
  626.         if (current_dist <= max_dist)
  627.         {
  628.             max_dist = current_dist;
  629.             close_marker = i;
  630.         }
  631.     }
  632.     return(close_marker);
  633. }
  634.  
  635.  
  636. /* 
  637.  * Returns a pseudo-random float between 0 and n.
  638.  */
  639. float generate_random_float(float n)
  640. {
  641.     static seeded = FALSE;
  642.     float result, r;
  643.     
  644.     if (! seeded)
  645.     {
  646.         srand48((long) getvaluator(MOUSEX));
  647.         seeded = TRUE;
  648.     }
  649.         
  650.     r = (float) drand48();
  651.     result = n * r;
  652.  
  653.     return(result);
  654. }
  655.  
  656.  
  657. /* The vertices of a cube centered about the origin with width 2 */
  658. Coord cube_vertex[8][3] =
  659.     {
  660.         {-1.0, -1.0, -1.0}, 
  661.         {-1.0, -1.0,  1.0}, 
  662.         {-1.0,  1.0,  1.0}, 
  663.         {-1.0,  1.0, -1.0}, 
  664.         { 1.0, -1.0, -1.0}, 
  665.         { 1.0, -1.0,  1.0}, 
  666.         { 1.0,  1.0,  1.0}, 
  667.         { 1.0,  1.0, -1.0}
  668.     };
  669.  
  670.  
  671. /*
  672.  * Draws the cube with vertices defined above.
  673.  */
  674. void draw_cube(void)
  675. {
  676.     bgnclosedline();
  677.     v3f(cube_vertex[0]);    
  678.     v3f(cube_vertex[1]);    
  679.     v3f(cube_vertex[2]);    
  680.     v3f(cube_vertex[3]);    
  681.     endclosedline();
  682.  
  683.     bgnclosedline();
  684.     v3f(cube_vertex[4]);    
  685.     v3f(cube_vertex[5]);    
  686.     v3f(cube_vertex[6]);    
  687.     v3f(cube_vertex[7]);
  688.     endclosedline();
  689.  
  690.     bgnline();
  691.     v3f(cube_vertex[0]);    
  692.     v3f(cube_vertex[4]);
  693.     endline();
  694.     
  695.     bgnline();
  696.     v3f(cube_vertex[1]);    
  697.     v3f(cube_vertex[5]);
  698.     endline();
  699.     
  700.     bgnline();
  701.     v3f(cube_vertex[2]);    
  702.     v3f(cube_vertex[6]);
  703.     endline();
  704.     
  705.     bgnline();
  706.     v3f(cube_vertex[3]);    
  707.     v3f(cube_vertex[7]);
  708.     endline();
  709. }
  710.  
  711.  
  712. void fake_view_volume(void)
  713. {
  714.     loadname(1);
  715.     draw_volume();
  716. }
  717.  
  718. void draw_volume(void)
  719. {
  720.     /* x = 1.0 */
  721.     bgnpolygon();
  722.     v3f(cube_vertex[4]);
  723.     v3f(cube_vertex[5]);
  724.     v3f(cube_vertex[6]);
  725.     v3f(cube_vertex[7]);
  726.     endpolygon();
  727.  
  728.     /* x = -1.0 */
  729.     bgnpolygon();
  730.     v3f(cube_vertex[0]);
  731.     v3f(cube_vertex[1]);
  732.     v3f(cube_vertex[2]);
  733.     v3f(cube_vertex[3]);
  734.     endpolygon();
  735.  
  736.     /* y = 1.0 */
  737.     bgnpolygon();
  738.     v3f(cube_vertex[3]);
  739.     v3f(cube_vertex[2]);
  740.     v3f(cube_vertex[6]);
  741.     v3f(cube_vertex[7]);
  742.     endpolygon();
  743.  
  744.     /* y = -1.0 */
  745.     bgnpolygon();
  746.     v3f(cube_vertex[0]);
  747.     v3f(cube_vertex[1]);
  748.     v3f(cube_vertex[5]);
  749.     v3f(cube_vertex[4]);
  750.     endpolygon();
  751.  
  752.     /* z = 1.0 */
  753.     bgnpolygon();
  754.     v3f(cube_vertex[1]);
  755.     v3f(cube_vertex[2]);
  756.     v3f(cube_vertex[6]);
  757.     v3f(cube_vertex[5]);
  758.     endpolygon();
  759.  
  760.     /* z = -1.0 */
  761.     bgnpolygon();
  762.     v3f(cube_vertex[0]);
  763.     v3f(cube_vertex[3]);
  764.     v3f(cube_vertex[7]);
  765.     v3f(cube_vertex[4]);
  766.     endpolygon();
  767. }
  768.  
  769. void fake_control_volumes(void)
  770. {
  771.     int i;
  772.  
  773.     for(i=0; i<current_markers; i++)
  774.     {
  775.         pushmatrix();
  776.         translate(geometry[i][0], geometry[i][1], geometry[i][2]);
  777.         scale(.02, .02, .02);
  778.         pushname(i);
  779.         draw_volume();
  780.         popname();
  781.         popmatrix();
  782.     }
  783. }
  784.  
  785.  
  786. Boolean hit_control_point(int *marker)
  787. {
  788.     long hit;
  789.     short buffer[2];
  790.  
  791.     picksize(10, 10);
  792.     
  793.     
  794.     initnames();
  795.     pick(buffer, 2);
  796.  
  797.     if (display_mode == TWO_D)
  798.         set_two_d_view();
  799.     else
  800.     {
  801.         set_three_d_view();
  802.         multmatrix(rotate_matrix);
  803.     }
  804.  
  805.     fake_control_volumes();
  806.     hit = endpick(buffer);
  807.  
  808.     *marker = buffer[1];
  809.     
  810.     return(hit != 0);
  811. }
  812.     
  813.